﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Generic;
using DimOS.DimSH;
using DimOS.H;
using DimOS.Internals;
using ValueType = DimOS.H.ValueType;

namespace DimOS.Plugs
{
    public static class List
    {
        public static bool Contains(List<string> source, string item)
        { if (source.Count == 0) return false; for (int i = 0; i < source
          .Count; i++) if (source[i] == item) return true; return false; }

        public static void Reverse(List<Value> list)
        { for (int i = 0; i < list.Count / 2; i++) { var temp = list[i]; list
          [i] = list[list.Count - i - 1]; list[list.Count - i - 1] = temp; } }

        public static void Insert(List<Value> list, int index, Value item)
        {
            var temp = new List<Value>(); for (int i = 0; i < list.Count; i++)
            { if (i == index) temp.Add(item); temp.Add(list[i]); } list = temp;
            if (list.Count == 0) list.Add(item);
        }

        public static bool Contains(List<Command> source, string name)
        {
            if (source.Count == 0) return false;
            for (int i = 0; i < source.Count; i++)
                if (source[i].Key == name) return true;
            return false;
        }

        public static void Insert(ref List<CharColor> list, int index, CharColor item)
        {
            //List.Insert is not working properly, so have to do it manually T_T
            var temp = new List<CharColor>(); for (int i = 0; i < list.Count; i++)
            { if (i == index) temp.Add(item); temp.Add(list[i]); } list = temp;
            if (list.Count == 0) list.Add(item);
        }



        public static void Remove(List<Value> source, List<Value> target)
        {
            
        }

        public static void Remove(List<Value> source, Value item)
        {

        }

        public static List<CharColor> Clone(this List<CharColor> list)
        {
            var result = new List<CharColor>(); for (int i = 0;
            i < list.Count; i++) result.Add(new CharColor(list
            [i].Character, list[i].Color)); return result;
        }

        public static List<Value> Clone(this List<Value> list)
        {
            var result = new List<Value>(); for (int i = 0; i <
            list.Count; i++) if (list[i].Type == ValueType.List)
            result.Add(list[i].Clone()); else result.Add(new
            Value(list[i])); return result;
        }

        public static List<List<CharColor>> Split(this List<CharColor> list, char separator, int limit = -1)
        {
            var result = new List<List<CharColor>>();
            result.Add(new List<CharColor>());
            for (int i = 0; i < list.Count; i++) 
            { if (result[result.Count - 1].Count >= limit) result.Add(new List<CharColor>());
              if (list[i].Character == separator) result.Add(new List<CharColor>());
              else result[result.Count - 1].Add(list[i]);} return result;
        }

        public static void SortByStartPosition(ref List<Token> list, int start, int end)
        {
            var pivot = list[(end - start) / 2 + start]; int i = start, j = end;
            while (i <= j)
            {
                while (list[i].StartPosition < pivot.StartPosition && i <= end) ++i;
                while (list[j].StartPosition > pivot.StartPosition && j >= start) --j;
                if (i <= j) { var temp = list[i]; list[i] = list[j]; list[j] = temp; ++i; --j; }
            }
            if (j > start) SortByStartPosition(ref list, start, j); if (i < end) SortByStartPosition(ref list, i, end);
        }

        public static void SortByPriority(ref List<Token> list, int start, int end)
        {
            var pivot = list[(end - start) / 2 + start]; int i = start, j = end;
            while (i <= j)
            {
                while (list[i].Priority < pivot.Priority && i <= end) ++i;
                while (list[j].Priority > pivot.Priority && j >= start) --j;
                if (i <= j) { var temp = list[i]; list[i] = list[j]; list[j] = temp; ++i; --j; }
            }
            if (j > start) SortByPriority(ref list, start, j); if (i < end) SortByPriority(ref list, i, end);
        }

        public static List<List<Token>> GroupByStartPosition(List<Token> list)
        {
            SortByStartPosition(ref list, 0, list.Count - 1);
            if (list.Count < 2) return new List<List<Token>>{list};

            var temp = new List<Token>{list[0]}; var result = new List<List<Token>>();
            for (int i = 1; i < list.Count; i++) //Group all tokens by StartPosition
            { if (list[i].StartPosition == temp[0].StartPosition) temp.Add(list[i]);
            else { result.Add(temp); temp = new List<Token>{list[i]}; }} result.Add(temp);
            return result;
        }

        public static void SortNaturally(List<Value> list, int start, int end)
        {
            string pivot = list[(end - start) / 2 + start].ToString(); int i = start, j = end;
            while (i <= j)
            {
                while (String.CompareNaturally(list[i].ToString(), pivot) < 0 && i <= end) ++i;
                while (String.CompareNaturally(list[j].ToString(), pivot) > 0 && j >= start) --j;
                if (i <= j) { var temp = list[i]; list[i] = list[j]; list[j] = temp; ++i; --j; }
            }
            if (j > start) SortNaturally(list, start, j); if (i < end) SortNaturally(list, i, end);
        }
    }
}
